package com.ds.infrastructure.hyperspace.container.internal.http;

import com.ds.infrastructure.hyperspace.common.config.TargetProtocolConfig;
import com.ds.infrastructure.hyperspace.container.endpoint.destination.TargetEndpointNode;
import com.ds.infrastructure.hyperspace.container.flow.context.HyperspaceDuplexFlowContext;
import com.ds.infrastructure.hyperspace.container.internal.http2.HyperspaceHttp2FrameWrapper;
import com.ds.infrastructure.hyperspace.container.internal.util.Http2Util;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http2.Http2Headers;
import io.netty.handler.codec.http2.Http2HeadersFrame;

import static io.netty.handler.codec.http.HttpHeaderNames.HOST;
import static io.netty.handler.codec.http2.Http2Headers.PseudoHeaderName.AUTHORITY;

/**
 * @author  Weishaoying
 */
public class NettyHttpHeaderOptimizer {

    public static void optimizeHttpHeader(HyperspaceDuplexFlowContext duplexFlowContext,
                                          HttpRequest httpRequest, TargetEndpointNode targetEndpointNode) {
        HttpHeaders httpHeaders = httpRequest.headers();
        String handlerHostHeader = duplexFlowContext.getContextHeader(HOST.toString());
        if (handlerHostHeader != null) {
            httpHeaders.set(HOST, handlerHostHeader);
            return;
        }

        TargetProtocolConfig protocolConfig = targetEndpointNode.getNodeConfig().getProtocolConfig();
        if (!protocolConfig.isOverrideHostHeader()) {
            return;
        }
        String customHostHeader = protocolConfig.getCustomHostHeader();
        if (customHostHeader == null) {
            httpHeaders.set(HOST, targetEndpointNode.getHostHeader());
        } else {
            httpHeaders.set(HOST, customHostHeader);
        }
    }

    public static void optimizeHttp2Header(HyperspaceDuplexFlowContext duplexFlowContext,
                                           Object data, TargetEndpointNode targetEndpointNode) {
        if (duplexFlowContext.getRequestStartState() != data) {
            return;
        }
        HyperspaceHttp2FrameWrapper http2FrameWrapper = (HyperspaceHttp2FrameWrapper) data;
        Http2HeadersFrame http2HeadersFrame = (Http2HeadersFrame) http2FrameWrapper.getFrameData();
        Http2Headers http2Headers = http2HeadersFrame.headers();
        String handlerHostHeader = duplexFlowContext.getContextHeader(AUTHORITY.value().toString());
        if (handlerHostHeader != null) {
            http2Headers.set(AUTHORITY.value(), Http2Util.newValue(handlerHostHeader));
            return;
        }
        TargetProtocolConfig protocolConfig = targetEndpointNode.getNodeConfig().getProtocolConfig();
        if (!protocolConfig.isOverrideHostHeader()) {
            return;
        }
        String customHostHeader = protocolConfig.getCustomHostHeader();
        if (customHostHeader == null) {
            http2Headers.set(AUTHORITY.value(), Http2Util.newValue(targetEndpointNode.getHostHeader()));
        } else {
            http2Headers.set(AUTHORITY.value(), Http2Util.newValue(customHostHeader));
        }
    }
}
